home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / decprom / fsDisk.tmp < prev    next >
Text File  |  1990-06-28  |  17KB  |  503 lines

  1. /* 
  2.  * fsDisk.c --
  3.  *
  4.  *    Routines related to managing local disks.  Each partition of a local
  5.  *    disk (partitions are defined by a table on the disk header) is
  6.  *    called a ``domain''.  FsAttachDisk attaches a domain into the file
  7.  *    system, and FsDeattachDisk removes it.  A domain is given
  8.  *    a number the first time it is ever attached.  This is recorded on
  9.  *    the disk so it doesn't change between boots.  The domain number is
  10.  *    used to identify disks, and a domain number plus a file number is
  11.  *    used to identify files.  Fsdm_DomainFetch is used to get the state
  12.  *    associated with a disk, and Fsdm_DomainRelease releases the reference
  13.  *    on the state.  FsDetachDisk checks the references on domains in
  14.  *    the normal (non-forced) case so that active disks aren't detached.
  15.  *
  16.  * Copyright 1987 Regents of the University of California
  17.  * All rights reserved.
  18.  * Permission to use, copy, modify, and distribute this
  19.  * software and its documentation for any purpose and without
  20.  * fee is hereby granted, provided that the above copyright
  21.  * notice appear in all copies.  The University of California
  22.  * makes no representations about the suitability of this
  23.  * software for any purpose.  It is provided "as is" without
  24.  * express or implied warranty.
  25.  */
  26.  
  27. #ifdef notdef
  28. static char rcsid[] = "$Header: /sprite/src/boot/decprom/RCS/fsDisk.c,v 1.1 90/02/16 16:14:11 shirriff Exp Locker: shirriff $ SPRITE (Berkeley)";
  29. #endif not lint
  30.  
  31.  
  32. #include "sprite.h"
  33.  
  34. #include "fsBoot.h"
  35. #include "kernel/devDiskLabel.h"
  36. #include "kernel/dev.h"
  37. #include "kernel/devFsOpTable.h"
  38. #include "kernel/machMon.h"
  39. /*
  40.  * fsDevice is copied into all Fsio_FileIOHandles.  It is used by the drivers
  41.  * to get to the partition and geometry information for the disk.
  42.  */
  43. Fs_Device fsDevice;
  44.  
  45. /*
  46.  * fsDomainPtr and fsRootHandlePtr are used by Fs_Open.
  47.  */
  48. static Fsdm_Domain fsDomain;
  49. Fsdm_Domain *fsDomainPtr = &fsDomain;
  50. static Fsio_FileIOHandle fsRootHandle;
  51. Fsio_FileIOHandle *fsRootHandlePtr = &fsRootHandle;
  52.  
  53. /*
  54.  * Forward declarations.
  55.  */
  56. static int    InstallLocalDomain();
  57. void        AddDomainFlags();
  58. static Boolean    IsDecLabel();
  59.  
  60. /*
  61.  *----------------------------------------------------------------------
  62.  *
  63.  * FsAttachDisk --
  64.  *
  65.  *    Make a particular local disk partition correspond to a prefix.
  66.  *    This makes sure the disk is up, reads the domain header,
  67.  *    and calls the initialization routine for the block I/O module
  68.  *    of the disk's driver.  By the time this is called the device
  69.  *    initialization routines have already been called from Dev_Config
  70.  *    so the device driver knows how the disk is partitioned into
  71.  *    domains.  This routine sees if the domain is formatted correctly,
  72.  *    and if so attaches it to the set of domains.
  73.  *
  74.  * Results:
  75.  *    SUCCESS if the disk was readable and had a good domain header.
  76.  *
  77.  * Side effects:
  78.  *    Sets up the Fsdm_DomainInfo for the domain.
  79.  *
  80.  *----------------------------------------------------------------------
  81.  */
  82. ReturnStatus
  83. FsAttachDisk(fsDevicePtr)
  84.     Fs_Device *fsDevicePtr;        /* Global FS device descriptor */
  85. {
  86.     ReturnStatus status;        /* Error code */
  87.     register Address buffer;        /* Read buffer */
  88.     int headerSector;            /* Starting sector of domain header */
  89.     int numHeaderSectors;        /* Number of sectors in domain header */
  90.     int summarySector;            /* Sector of summary information. */
  91.     Fsdm_SummaryInfo *summaryInfoPtr;    /* Pointer to summary info. */
  92.     int amountRead;            /* Returned from read call */
  93.     int devType;            /* Device type index */
  94.  
  95.     /*
  96.      * Open the raw disk device so we can grub around in the header info.
  97.      */
  98.     Mach_MonPrintf("FsAttachDisk: ptr = %x\n", fsDevicePtr);
  99.     devType = DEV_TYPE_INDEX(fsDevicePtr->type);
  100.     status = (*devFsOpTable[devType].open)(&fsDevice);
  101.     if (status != SUCCESS) {
  102.     Mach_MonPrintf("Failure\n");
  103.     return(status);
  104.     }
  105.     Mach_MonPrintf("Mallocing\n");
  106.     buffer = (Address)malloc(DEV_BYTES_PER_SECTOR);
  107.     Mach_MonPrintf("Done mallocing\n");
  108.  
  109.     /*
  110.      * Read the 31st sector of the partition.  It has a copy of the
  111.      * 31st sector of the whole disk which describes how the rest of the
  112.      * domain's zero'th cylinder is layed out.
  113.      */
  114.     status = (*devFsOpTable[devType].read)(&fsDevice,
  115.         DEC_LABEL_SECTOR*DEV_BYTES_PER_SECTOR,
  116.         DEV_BYTES_PER_SECTOR, buffer, &amountRead);
  117.     if (status != SUCCESS) {
  118. #ifndef NO_PRINTF
  119.     Mach_MonPrintf("label (sector 31) read fail\n");
  120. #endif
  121.     return(status);
  122.     }
  123.     Mach_MonPrintf("Checking format\n");
  124.     /*
  125.      * Check for different disk formats, and figure out how the rest
  126.      * of the zero'th cylinder is layed out.
  127.      */
  128.     if (((Dec_DiskLabel *)buffer)->magic != DEC_LABEL_MAGIC) {
  129. #ifndef NO_PRINTF
  130.     Mach_MonPrintf("Bad magic <%x>\n", ((Dec_DiskLabel *)buffer)->magic);
  131. #endif
  132.     }
  133.  
  134.     headerSector = ((Dec_DiskLabel *)buffer)->domainSector;
  135.     numHeaderSectors = ((Dec_DiskLabel *)buffer)->numDomainSectors;
  136.     /*
  137.      * Read the domain header and save it with the domain state.
  138.      */
  139.     buffer = (Address)malloc(DEV_BYTES_PER_SECTOR * numHeaderSectors);
  140.     status = (*devFsOpTable[devType].read)(&fsDevice,
  141.         headerSector * DEV_BYTES_PER_SECTOR,
  142.         numHeaderSectors * DEV_BYTES_PER_SECTOR,
  143.         buffer, &amountRead);
  144.     Mach_MonPrintf("Read header\n");
  145.     if (status != SUCCESS) {
  146. #ifndef NO_PRINTF
  147.     Mach_MonPrintf("Domain fail\n");
  148. #endif
  149.     return(status);
  150.     } else if (((Fsdm_DomainHeader *)buffer)->magic != FSDM_DOMAIN_MAGIC) {
  151. #ifndef NO_PRINTF
  152.     Mach_MonPrintf("Bad magic <%x>\n",
  153.         ((Fsdm_DomainHeader *)buffer)->magic);
  154. #endif
  155.     return(FAILURE);
  156.     }
  157.  
  158.     fsDomainPtr->headerPtr = (Fsdm_DomainHeader *) buffer;
  159.  
  160.      /*
  161.      * Set up the ClientData part of *devicePtr to reference the
  162.      * Fsdm_Geometry part of the domain header.  This is used by the
  163.      * block I/O routines.
  164.      */
  165.     fsDevicePtr->data = (ClientData)&fsDomainPtr->headerPtr->geometry;
  166.  
  167.     /*
  168.      * Set up a file handle for the root directory.  What is important
  169.      * is the device info (for Block IO) and the file descriptor itself.
  170.      */
  171.     Mach_MonPrintf("Init'ing handle\n");
  172.     FsInitFileHandle(fsDomainPtr, FSDM_ROOT_FILE_NUMBER, fsRootHandlePtr);
  173.     Mach_MonPrintf("Done\n");
  174.     return(SUCCESS);
  175. }
  176.  
  177.  
  178. /*
  179.  *----------------------------------------------------------------------
  180.  *
  181.  * IsSunLabel --
  182.  *
  183.  *    Poke around in the input buffer and see if it looks like
  184.  *    a Sun format disk label.
  185.  *
  186.  * Results:
  187.  *    TRUE or FALSE
  188.  *
  189.  * Side effects:
  190.  *    None.
  191.  *
  192.  *----------------------------------------------------------------------
  193.  */
  194. #ifdef notdef
  195. static Boolean
  196. IsSunLabel(buffer)
  197.     Address buffer;    /* Buffer containing zero'th sector */
  198. {
  199.     register Sun_DiskLabel *sunLabelPtr;
  200.  
  201.     sunLabelPtr = (Sun_DiskLabel *)buffer;
  202.     if (sunLabelPtr->magic == SUN_DISK_MAGIC) {
  203.     /*
  204.      * Should check checkSum...
  205.      */
  206.     return(TRUE);
  207.     } else {
  208.     return(FALSE);
  209.     }
  210. }
  211. #endif
  212.  
  213. /*
  214.  *----------------------------------------------------------------------
  215.  *
  216.  * IsSpriteLabel --
  217.  *
  218.  *    Poke around in the input buffer and see if it looks like
  219.  *    a Sprite format disk header.
  220.  *
  221.  * Results:
  222.  *    TRUE or FALSE
  223.  *
  224.  * Side effects:
  225.  *    None.
  226.  *
  227.  *----------------------------------------------------------------------
  228.  */
  229. #ifdef notdef
  230. static Boolean
  231. IsSpriteLabel(buffer)
  232.     Address buffer;    /* Buffer containing zero'th sector */
  233. {
  234.     register FsDiskHeader *diskHeaderPtr;
  235.     register int index;
  236.     register int checkSum;
  237.  
  238.     diskHeaderPtr = (FsDiskHeader *)buffer;
  239.     if (diskHeaderPtr->magic == FSDM_DISK_MAGIC) {
  240.         return(TRUE);
  241.     }
  242.     }
  243.     return(FALSE);
  244. }
  245. #endif
  246.  
  247. /*
  248.  *----------------------------------------------------------------------
  249.  * The following routines are used by device drivers to map from block
  250.  * and sector numbers to disk addresses.  There are two sets, one for
  251.  * drivers that use logical sector numbers (i.e. SCSI) and the other
  252.  * for <cyl,head,sector> format disk addresses.
  253.  *----------------------------------------------------------------------
  254.  */
  255.  
  256. /*
  257.  *----------------------------------------------------------------------
  258.  *
  259.  * Fs_BlocksToSectors --
  260.  *
  261.  *    Convert from block indexes (actually, fragment indexes) to
  262.  *    sectors using the geometry information on the disk.  This
  263.  *    is a utility for block device drivers.
  264.  *
  265.  * Results:
  266.  *    The sector number that corresponds to the fragment index.
  267.  *    The caller has to make sure that its I/O doesn't cross a
  268.  *    filesystem block boundary.
  269.  *
  270.  * Side effects:
  271.  *    None.
  272.  *
  273.  *----------------------------------------------------------------------
  274.  */
  275. #define SECTORS_PER_FRAG    (FS_FRAGMENT_SIZE / DEV_BYTES_PER_SECTOR)
  276. #if defined(SCSI_DISK_BOOT) || defined(SUN_PROM_BOOT)
  277. int
  278. Fs_BlocksToSectors(fragNumber, data)
  279.     int fragNumber;    /* Fragment index to map into block index */
  280.     ClientData data;    /* ClientData from the device info */
  281. {
  282.     register Fsdm_Geometry *geoPtr;
  283.     register int sectorNumber;    /* The sector corresponding to the fragment */
  284.     register int cylinder;    /* The cylinder number of the fragment */
  285.     register int rotationalSet;    /* The rotational set with cylinder of frag */
  286.     register int blockNumber;    /* The block number within rotational set */
  287.  
  288.     geoPtr         = (Fsdm_Geometry *)data;
  289.     blockNumber        = fragNumber / FS_FRAGMENTS_PER_BLOCK;
  290.     cylinder        = blockNumber / geoPtr->blocksPerCylinder;
  291.     if (geoPtr->rotSetsPerCyl > 0) {
  292.     /*
  293.      * Do fancy rotational set mapping.
  294.      */
  295.     blockNumber        -= cylinder * geoPtr->blocksPerCylinder;
  296.     rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  297.     blockNumber        -= rotationalSet * geoPtr->blocksPerRotSet;
  298.  
  299.     sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
  300.               geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
  301.               rotationalSet +
  302.               geoPtr->blockOffset[blockNumber];
  303.     sectorNumber += (fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
  304.     } else {
  305.     /*
  306.      * Do straight-forward mapping.
  307.      */
  308.     sectorNumber = geoPtr->sectorsPerTrack * geoPtr->numHeads * cylinder +
  309.             fragNumber * SECTORS_PER_FRAG - cylinder * 
  310.             geoPtr->blocksPerCylinder * FS_FRAGMENTS_PER_BLOCK *
  311.             SECTORS_PER_FRAG;
  312.     }
  313.  
  314.     return(sectorNumber);
  315. }
  316. #endif
  317.  
  318. /*
  319.  *----------------------------------------------------------------------
  320.  *
  321.  * Fs_BlocksToDiskAddr --
  322.  *
  323.  *    Convert from block indexes (actually, fragment indexes) to
  324.  *    disk address (head, cylinder, sector) using the geometry information
  325.  *     on the disk.  This is a utility for block device drivers.
  326.  *
  327.  * Results:
  328.  *    The disk address that corresponds to the disk address.
  329.  *    The caller has to make sure that its I/O doesn't cross a
  330.  *    filesystem block boundary.
  331.  *
  332.  * Side effects:
  333.  *    None.
  334.  *
  335.  *----------------------------------------------------------------------
  336.  */
  337. #ifdef XYLOGICS_BOOT
  338. void
  339. Fs_BlocksToDiskAddr(fragNumber, data, diskAddrPtr)
  340.     int fragNumber;    /* Fragment index to map into block index */
  341.     ClientData data;    /* ClientData from the device info */
  342.     Dev_DiskAddr *diskAddrPtr;
  343. {
  344.     register Fsdm_Geometry *geoPtr;
  345.     register int sectorNumber;    /* The sector corresponding to the fragment */
  346.     register int cylinder;    /* The cylinder number of the fragment */
  347.     register int rotationalSet;    /* The rotational set with cylinder of frag */
  348.     register int blockNumber;    /* The block number within rotational set */
  349.  
  350.     geoPtr         = (Fsdm_Geometry *)data;
  351.     /*
  352.      * Map to block number because the rotational sets are laid out
  353.      * relative to blocks.  After that the cylinder is easy because we know
  354.      * blocksPerCylinder.  To get the head and sector we first get the
  355.      * rotational set (described in fsDisk.h) of the block and the
  356.      * block's sector offset (relative to the rotational set!).  This complex
  357.      * algorithm crops up because there isn't necessarily an even number
  358.      * of blocks per track.  The 'blockOffset' array in the geometry gives
  359.      * a sector index of each successive block in a rotational set. Finally,
  360.      * we can use the sectorsPerTrack to get the head and sector.
  361.      */
  362.     blockNumber        = fragNumber / FS_FRAGMENTS_PER_BLOCK;
  363.     cylinder        = blockNumber / geoPtr->blocksPerCylinder;
  364.     blockNumber        -= cylinder * geoPtr->blocksPerCylinder;
  365.     diskAddrPtr->cylinder = cylinder;
  366.  
  367.     rotationalSet    = blockNumber / geoPtr->blocksPerRotSet;
  368.     blockNumber        -= rotationalSet * geoPtr->blocksPerRotSet;
  369. /*
  370.  * The follow statment had to be broken into two because the compiler used
  371.  * register d2 to do the modulo operation, but wasn't saving its value.
  372.  */
  373.     sectorNumber    = geoPtr->sectorsPerTrack * geoPtr->tracksPerRotSet *
  374.               rotationalSet + geoPtr->blockOffset[blockNumber];
  375.     sectorNumber    +=
  376.             (fragNumber % FS_FRAGMENTS_PER_BLOCK) * SECTORS_PER_FRAG;
  377.  
  378.     diskAddrPtr->head    = sectorNumber / geoPtr->sectorsPerTrack;
  379.     diskAddrPtr->sector = sectorNumber -
  380.               diskAddrPtr->head * geoPtr->sectorsPerTrack;
  381. }
  382. #endif
  383.  
  384. /*
  385.  *----------------------------------------------------------------------
  386.  *
  387.  * Fs_SectorsToRawDiskAddr --
  388.  *
  389.  *      Convert from a sector offset to a raw disk address (cyl, head,
  390.  *      sector) using the geometry information on the disk.  This is a
  391.  *      utility for raw device drivers and does not pay attention to the
  392.  *      rotational position of filesystem disk blocks.
  393.  *
  394.  *    This should be moved to Dev
  395.  *
  396.  * Results:
  397.  *    The disk address that corresponds exactly to the byte offset.
  398.  *
  399.  * Side effects:
  400.  *    None.
  401.  *
  402.  *----------------------------------------------------------------------
  403.  */
  404. #ifdef XYLOGICS_BOOT
  405. int
  406. Fs_SectorsToRawDiskAddr(sector, numSectors, numHeads, diskAddrPtr)
  407.     int sector;        /* Sector number (counting from zero 'til the total
  408.              * number of sectors in the disk) */
  409.     int numSectors;    /* Number of sectors per track */
  410.     int numHeads;    /* Number of heads on the disk */
  411.     Dev_DiskAddr *diskAddrPtr;
  412. {
  413.     register int sectorsPerCyl;    /* The rotational set with cylinder of frag */
  414.  
  415.     sectorsPerCyl        = numSectors * numHeads;
  416.     diskAddrPtr->cylinder    = sector / sectorsPerCyl;
  417.     sector            -= diskAddrPtr->cylinder * sectorsPerCyl;
  418.     diskAddrPtr->head        = sector / numSectors;
  419.     diskAddrPtr->sector        = sector - numSectors * diskAddrPtr->head;
  420. }
  421. #endif
  422.  
  423.  
  424. /*
  425.  *----------------------------------------------------------------------
  426.  *
  427.  * FsDeviceBlockIO --
  428.  *
  429.  *    Map a file system block address to a block device block address 
  430.  *    perform the requested operation.
  431.  *
  432.  * NOTE: This routine is temporary and should be replaced when the file system
  433.  *     is converted to use the async block io interface.
  434.  *
  435.  * Results:
  436.  *    The return status of the operation.
  437.  *
  438.  * Side effects:
  439.  *    Blocks may be written or read.
  440.  *
  441.  *----------------------------------------------------------------------
  442.  */
  443.  
  444. ReturnStatus
  445. FsDeviceBlockIO(readWriteFlag, devicePtr, fragNumber, numFrags, buffer)
  446.     int readWriteFlag;        /* FS_READ or FS_WRITE */
  447.     Fs_Device *devicePtr;    /* Specifies device type to do I/O with */
  448.     int fragNumber;        /* CAREFUL, fragment index, not block index.
  449.                  * This is relative to start of device. */
  450.     int numFrags;        /* CAREFUL, number of fragments, not blocks */
  451.     Address buffer;        /* I/O buffer */
  452. {
  453.     ReturnStatus status;    /* General return code */
  454.     int firstSector;        /* Starting sector of transfer */
  455.     DevBlockDeviceRequest    request;
  456.     int                transferCount;
  457.     int                devType;
  458.  
  459.     devType = DEV_TYPE_INDEX(devicePtr->type);
  460.     if ((fragNumber % FS_FRAGMENTS_PER_BLOCK) != 0) {
  461.     /*
  462.      * The I/O doesn't start on a block boundary.  Transfer the
  463.      * first few extra fragments to get things going on a block boundary.
  464.      */
  465.     register int extraFrags;
  466.  
  467.     extraFrags = FS_FRAGMENTS_PER_BLOCK -
  468.             (fragNumber % FS_FRAGMENTS_PER_BLOCK);
  469.     if (extraFrags > numFrags) {
  470.         extraFrags = numFrags;
  471.     }
  472.     firstSector = Fs_BlocksToSectors(fragNumber, devicePtr->data);
  473.     status = (*devFsOpTable[devType].read)(devicePtr,
  474.         firstSector * DEV_BYTES_PER_SECTOR,
  475.         extraFrags * FS_FRAGMENT_SIZE, buffer, &transferCount);
  476.     if (status != SUCCESS) {
  477. #ifndef NO_PRINTF
  478.         Mach_MonPrintf("Fragment read failure\n");
  479. #endif
  480.     }
  481.     extraFrags = transferCount / FS_FRAGMENT_SIZE;
  482.     fragNumber += extraFrags;
  483.     buffer += transferCount;
  484.     numFrags -= extraFrags;
  485.     }
  486.     if (numFrags > 0) {
  487.     /*
  488.      * Transfer the left over fragments.
  489.      */
  490.     firstSector = Fs_BlocksToSectors(fragNumber, devicePtr->data);
  491.     status = (*devFsOpTable[devType].read)(devicePtr,
  492.         firstSector * DEV_BYTES_PER_SECTOR,
  493.         numFrags * FS_FRAGMENT_SIZE, buffer, &transferCount);
  494.     if (status != SUCCESS) {
  495. #ifndef NO_PRINTF
  496.         Mach_MonPrintf("Last fragment read failure\n");
  497. #endif
  498.     }
  499.     }
  500.     return(status);
  501. }
  502.  
  503.